package com.gxm.base.datatype.string.面试题;

/**


 必备知识：

 java 程序在运行的时候,　会创建一个字符串缓冲池。对于诸如　String s1 ="Programming";　
 String s3 = "Program";　String s4 = "ming";　这些字符串常量，程序首先会在这个　String　缓冲池中寻找相同值的对象。
 若它们在池中不存在，程序则将这些字符串常量创建于池中。若在池中找到了相同值得对象，则这个找到的对象的引用，就是新变量的引用。
 由此可见，字符串常量池中一个给定值得对象，最多只有一个。
 用操作符 new 创建的字符串对象，　如 String s2 = new String("Programming");
 或者有字符串变量、操作符 '+'　参与的表达式，如 String s6 = s3 + s4;　
 这样得到的引用，都要放到内存(堆heap)中保存。故，在堆中，若有几个值相同的对象，它们分别都会有各自的地址。
 字符串的一个成员方法 public String intern(),返回字符串对象的规范化表示形式。
 当调用 intern 方法时，如果池已经包含一个等于此 String 对象的字符串（用 equals(Object) 方法确定），则返回池中的字符串。
 否则，将此 String 对象添加到池中，并返回此 String 对象的引用。

 解释：

 由必备知识 1,2所示，s1创建于字符串缓冲池，而s2创建于内存(堆)中，尽管二者内容都是"Programming",但地址不在一个区，故比较地址的结果为 false。
 至于　String s5 = "Program" + "ming";的操作，　由于表达式的两个算子都是字符串常量，所以操作始终在池内进行。在池内找到 "Program" 和 "ming"之后，将两者连接成 "Programming", 然后，又在池内找到了相同值的对象s1，于是就将这个地址，赋予 s5。因此，比较s1 和 s5　的地址，当然相同，结果为 true。
 如预备知识1、２所示，s6的地址，存在堆里。而s1的地址存在池里。尽管两者值相同，但地址一定不同，结果为 false。
 如预备知识3所示，因为s6调用了它的成员方法inner()，结果返回了一个在池中的、具有相同值“Programming”的对象s1的地址。用它和 s1的地址相比较，当然相等，结果为 true。
 如预备知识3所示，s2的地址在堆里，s2.inner()　的地址在池里。一个在堆中，一个在池内，二者比较，肯定不等，结果为false。


 */
public class StringEqualTest {
    public static void main(String[] args) {
        //String 变量 的 引用关系
        String s1 = "Programming";
        String s2 = new String("Programming");
        String s3 = "Program";
        String s4 = "ming";
        String s5 = "Program" + "ming";
        String s6 = s3 + s4;
        String s7 = "Programming";
        System.out.println(s1 == s2); //false
        System.out.println(s1 == s5); //true
        System.out.println(s1 == s6); //false
        System.out.println(s1 == s6.intern()); //true
        System.out.println(s2 == s2.intern()); //false
        System.out.println(s1 == s7); //true
    }
}
